<?php

	/**
	 * @see Bike_Initial
	 */
	require_once 'Bike/Initial.php';
	
	/**
	 * @see Bike_Controller_Router_Handler_Interface
	 */
	require_once 'Bike/Controller/Router/Handler/Interface.php';
	
	
	class Bike_Language extends Bike_Initial implements Bike_Controller_Router_Handler_Interface
	{
		const LANGUAGE_DEFAULT = 'en';
		const LANGUAGE_REGEXP_2 = '[a-z]{2}';
		const LANGUAGE_REGEXP_3 = '[a-z]{3}';
		const LANGUAGE_FIELDNAME_2 = 'code2';
		const LANGUAGE_FIELDNAME_3 = 'code3';

		static protected $_instance;

		protected $_name;
		protected $_default = self::LANGUAGE_DEFAULT;
		protected $_regexp = self::LANGUAGE_REGEXP_2;
		protected $_charset = 'UTF-8';
		protected $_translationPaths = array();
		protected $_translationSourceFormats = array();
		protected $_languages;
		protected $_language;
		protected $_languageObj;
		protected $_locale;
		protected $_multi = False;
		protected $_incorrect;

		static public function getInstance()
		{
			if(is_null(self::$_instance))
			{
				self::$_instance = new self();
			}
			return self::$_instance;
		}

		public function getName()
		{
			return $this->_name;
		}

		public function setName($Name)
		{
			$this->_name = $Name;
			return $this;
		}

		public function getRouteParam()
		{
			return array($this->getName() => $this->getValue());
		}

		public function setTranslationPaths($Paths)
		{
			$this->_translationPaths = $Paths;
			return $this;
		}

		public function getTranslationPaths()
		{
			return $this->_translationPaths;
		}

		public function setCharset($Charset)
		{
			$this->_charset = $Charset;
			return $this;
		}

		public function getCharset()
		{
			return $this->_charset;
		}

		public function setTranslationSourceFormats($SourceFormats)
		{
			$this->_translationSourceFormats = $SourceFormats;
			return $this;
		}

		public function getTranslationSourceFormats()
		{
			return $this->_translationSourceFormats;
		}

		public function addTranslationPath($Path)
		{
			array_push($this->_translationPaths, $Path);
		}

		public function setDefault($Language)
		{			try
			{				$this->checkLanguage($Language);
				$this->_default = $Language;
			}
			catch(Bike_Controller_Router_Handler_Exception $e)
			{				$this->_default = self::LANGUAGE_DEFAULT;
			}
		}

		public function getDefault()
		{
			return $this->_default;
		}

		protected function checkLanguage($Language)
		{			if(!preg_match("/^".$this->getRegexp()."$/", $Language))
			{				Throw new Bike_Controller_Router_Handler_Exception('Language "'.$Language.'" does not match the regular expression');
			}
		}

		public function setAlpha($Alpha)
		{			switch($Alpha)
			{				case 3:
						$this->_regexp = self::LANGUAGE_REGEXP_3;
						Bike_Model_Language::setCodeFieldName(self::LANGUAGE_FIELDNAME_3);
						break;
				case 2:
				default:
						$this->_regexp = self::LANGUAGE_REGEXP_2;
						Bike_Model_Language::setCodeFieldName(self::LANGUAGE_FIELDNAME_2);
			}
		}

		public function getRegexp()
		{			return $this->_regexp;
		}

		public function getLanguages()
		{
			if(is_null($this->_languages))
			{
				$Mapper = Bike_Model_Mapper_Language::getInstance();
				$this->_languages = $Mapper->fetchAll($Mapper->select());
			}
			return $this->_languages;
		}

		public function getLanguage()
		{
			return is_null($this->_language) ? $this->getDefault() : $this->_language;
		}

		public function getLanguageObj()
		{
			if(is_null($this->_languageObj))
			{				foreach($this->getLanguages() as $Language)
				{					if($this->getLanguage() == $Language->getCode())
					{						$this->_languageObj = $Language;
					}
				}
			}
			return $this->_languageObj;
		}

		public function setLanguage($Language)
		{
			$this->checkLanguage($Language);
			$this->_language = $Language;
			return $this;
		}

		public function setLocale(array $Locale)
		{			foreach($Locale as $language => $locale)
			{				$this->checkLanguage($language);
			}
			$this->_locale = $Locale;
			return $this;
		}

		public function getLocale($Language=null)
		{
			if(is_null($Language))
			{				$Language = $this->getLanguage();
			}
			$locale = $this->getLocaleArray();
			return $locale[$Language];
		}

		public function getLocaleArray()
		{
			if(is_null($this->_locale))
			{
				$locale = array();
				foreach($this->getLanguages() as $Language)
				{					$locale[$Language->getCode()] = $Language->getLocale();
				}
				$this->_locale = $locale;
			}
			return (array) $this->_locale;
		}

		public function setMulti($Multi=True)
		{			$this->_multi = $Multi;
		}

		public function route(Zend_Controller_Request_Abstract $Request)
		{
         	if($this->_multi)
	        {
				preg_match("/^\/([^\/]+)/is", $Request->getPathInfo(), $matches);
				$language = @$matches[1];
				$accessor = @$matches[0];
				if($language)
				{
					try
					{
						$this->setLanguage($language);
						$Request->setPathInfo(substr($Request->getPathInfo(), strlen($accessor)));
					}
					catch(Bike_Controller_Router_Handler_Exception $e)
					{
						$this->setIncorrect();
					}
				}
	        }
	        $flagLangExists = False;
        	foreach($this->getLanguages() as $Language)
        	{
        		$lang = $Language->getCode();
        		if(!$lang || !preg_match("/^".$this->getRegexp()."$/", $lang))
	        	{
	        		Throw new Bike_Controller_Router_Handler_Exception('Invalid config parameter: plugins.language.locale; key: '.$lang);
	        	}
	        	if($lang == $this->getLanguage())
	        	{
	        		$flagLangExists = True;
	        	}
        	}
        	if($this->_multi)
	        {
	        	if(!$flagLangExists)
	        	{
	                $this->setIncorrect();
	        	}
	      	}
	      	$bootstrap = Zend_Controller_Front::getInstance()->getBootstrap();
	      	$bootstrap->bootstrap('locale')
						->getPluginResource('locale')
						->getLocale()
						->setLocale($this->getLocale());
			$bootstrap->bootstrap('translate')
						->getPluginResource('translate')
						->getTranslate()
						->getAdapter()
						->setLocale($this->getLocale());
	      	return $this->getRouteParam();
		}

		public function getValue()
		{			return $this->getLanguage();
		}

		public function assemble(array $Params)
		{			if(!$this->_multi)
			{				return False;
			}
			$Value = $this->getValue();
			if(isset($Params[$this->getName()]))
			{				try
				{
					$Value = $Params[$this->getName()];
					$this->checkLanguage($Value);
				}
				catch(Bike_Controller_Router_Handler_Exception $e)
				{				}
			}
			return $Value;
		}

		protected function setIncorrect()
		{			Throw new Bike_Controller_Router_Handler_Exception('Incorrect language', 404);
		}

		public function __toString()
		{			return $this->getLanguage();
		}
	}
